#ifndef PCPS_STOCHASTIC_OPTIMIZATION_HEADER
#define PCPS_STOCHASTIC_OPTIMIZATION_HEADER

#include <src/pcps.h>
#include <src/accumulator.h>

namespace pcps {

  //-------------------------------------------------------------------------------
  // pcps::stochastic_iterations-- Iteratively performs stochastic sampling of a
  //                               wavefunction.  This function can be used to
  //                               optimize the wavefunction, or simply to compute
  //                               its properties.
  //
  //                               The behavior is governed by which accumulators
  //                               are provided, how many iterations are requested,
  //                               and the sample and burn in lengths.
  //
  //                               print_freq and dump_freq dictate which
  //                               iterations should print information and dump
  //                               the wavefunction to disk.
  //-------------------------------------------------------------------------------

  template <class SCALAR, class PART, class REF>
  void stochastic_iterations(const pcps::Input & userinp,
                             const pcps::Hamiltonian<SCALAR> & ham,
                             pcps::Wavefunction<SCALAR> & wfn,
                             std::vector<boost::shared_ptr<pcps::ProcessAccum<SCALAR, PART, REF> > > & accumulators,
                             const int max_iter,
                             const int print_freq,
                             const int dump_freq,
                             const long int sample_length,   // number of samples to take on EACH thread
                             const long int burn_in_length); // number burn in steps for each thread's markov chain

  //-------------------------------------------------------------------------------
  // pcps::stochastic_opt_detail -- Optimizes the wavefunction using one of a
  //                                number of algorithms that rely on stochastic
  //                                sampling.
  //
  //                                This function chooses which optimization to
  //                                perform, creates the necessary accumulators,
  //                                and sends the necessary instructions to the
  //                                stochastic_iterations function.
  //-------------------------------------------------------------------------------

  template <class SCALAR, class PART, class REF>
  void stochastic_opt_detail(const pcps::Input & userinp, const pcps::Hamiltonian<SCALAR> & ham, pcps::Wavefunction<SCALAR> & wfn);

  //-------------------------------------------------------------------------------
  // pcps::stochastic_optimization -- Optimizes the wavefunction using one of a
  //                                  number of algorithms that rely on stochastic
  //                                  sampling.
  //
  //                                  This function chooses which particle type and
  //                                  reference type we are using and calls the
  //                                  appropriate version of stochastic_opt_detail.
  //-------------------------------------------------------------------------------

  template <class SCALAR>
  void stochastic_optimization(const pcps::Input & userinp, const pcps::Hamiltonian<SCALAR> & ham, pcps::Wavefunction<SCALAR> & wfn);

} // end namespace pcps

#endif
